﻿using System.IO.Ports;

namespace PLCSharp.Views.Connects.SerialPort
{
    public class SerialPortService
    {
        public static string[] GetPortNames() => System.IO.Ports.SerialPort.GetPortNames();

        public System.IO.Ports.SerialPort mySerial;

        public SerialPortService(string portName, int baudRate = 9600, int parity = 0, int stopBits = 1, int dataBits = 8)
        {
            mySerial = new()
            {
                PortName = portName,
                BaudRate = baudRate,
                Parity = (System.IO.Ports.Parity)parity,
                StopBits = (StopBits)stopBits,
                DataBits = dataBits,
                Handshake = Handshake.None,
                WriteTimeout = 100
            };
            mySerial.DataReceived += DataReceivedHandlerScan;

        }

        public void Open()
        {
            try
            {
                mySerial.Open();
            }
            catch (Exception ex)
            {
                Log?.Invoke(ex.Message);
            }
        }

        public void Close()
        {
            mySerial.Close();
        }

        public bool IsOpen => mySerial.IsOpen;


        public event Action<byte[]> ReceiveBytes;

        public event Action<string> Log;

        readonly byte[] readBuffer = new byte[1024];
        private void DataReceivedHandlerScan(object sender, SerialDataReceivedEventArgs e)
        {


            var spReceive = (System.IO.Ports.SerialPort)sender;
            var count = spReceive.BytesToRead;
            spReceive.Read(readBuffer, 0, count);
            var receiveBuffer = readBuffer[0..count];
            ReceiveBytes?.Invoke(receiveBuffer);
        }

        async public Task<bool> SendAsync(string port, string msg)
        {
            if (string.IsNullOrEmpty(msg))
                return false;
            try
            {
                if (mySerial.PortName != port)
                {
                    mySerial.Close();
                    mySerial.PortName = port;
                }

                if (!mySerial.IsOpen) //如果端口没有打开
                {
                    mySerial.Open(); //打开端口
                }

                await Task.Run(() => mySerial.Write(msg));

                return true;
            }
            catch (Exception ex)
            {
                Log?.Invoke(ex.Message);
                return false;
            }
        }

        async public Task<bool> SendAsync(string port, byte[] buffer)
        {
            try
            {
                if (mySerial.PortName != port)
                {
                    mySerial.Close();
                    mySerial.PortName = port;
                }

                if (!mySerial.IsOpen) //如果端口没有打开
                {
                    mySerial.Open(); //打开端口
                }

                await Task.Run(() => mySerial.Write(buffer, 0, buffer.Length));

                return true;
            }
            catch (Exception ex)
            {
                Log?.Invoke(ex.Message);
                return false;
            }
        }
    }
}